#!/usr/bin/env python
import pygtk
pygtk.require('2.0')
import gtk
import gnome
import gnomeapplet
import sys
import time
import os
import signal
import gtk.glade
import gconf

INSTALL_PREFIX='/usr/lib/cryptsetupapplet'

class CryptSetupApplet(gtk.EventBox):
  def __init__(self,applet,iid):
    gtk.EventBox.__init__(self)
    self.tooltips=gtk.Tooltips()
    self.applet=applet
    self.applet.add_preferences("/schemas/apps/cryptsetupapplet")
    self.prefs_key=self.applet.get_preferences_key()
    self.gconf = gconf.client_get_default()
    try:
      self.gconf.add_dir(self.prefs_key,gconf.CLIENT_PRELOAD_NONE)
      self.read_prefs()
    except:
      pass  
    self.wTree=gtk.glade.XML(INSTALL_PREFIX+"/"+"cryptsetupapplet.glade")
    self.wTree.signal_autoconnect(self)

    try:
      os.system("losetup '%s' '%s'"%(self.dm_device,self.loop_file))
    except:
      pass
    self.locked=not self.is_mounted()
    self.applet=applet
    self.image=gtk.Image()
    self.update_icon()
    self.update_tip()
    self.add(self.image)
    menuXml = """
    <popup name="button3">
    <menuitem name="About Item" verb="About" _label="%s" pixtype="stock" pixname="gtk-about"/>
    <menuitem name="Config Item" verb="Config" _label="%s" pixtype="stock" pixname="gtk-preferences"/>
    </popup>
    """
    menuXml = menuXml % ("_About", "_Preferences")

    applet.setup_menu(menuXml, [
    	("About", self.on_about),
    	("Config", self.on_prefs)
    	], applet)
    self.connect("button-press-event",self.on_click)
    self.connect("destroy",self.on_destroy)
#    signal.signal(signal.SIGINT,self.int_handler)    

  def int_handler(self,signum,frame):
    self.unmount()

  def fstab_entry_for_dev(self,dev):
    try:	
      return filter(lambda x:len(x)>0 and x.split()[0]=='/dev/mapper/'+self.dm_name,open('/etc/fstab').read().split('\n'))[0].split()
    except:
      return []
        
  def read_prefs(self):
    self.dm_name=self.gconf.get_string(self.prefs_key+"/name")
    self.dm_device=self.gconf.get_string(self.prefs_key+"/device")
    self.loop_file=self.gconf.get_string(self.prefs_key+"/loop_file")
    self.auto_open=self.gconf.get_bool(self.prefs_key+"/auto_open")
    self.fstab_entry=self.fstab_entry_for_dev('/dev/mapper/'+self.dm_name)
    
  def write_prefs(self):
    self.gconf.set_string(self.prefs_key+"/name",self.dm_name)
    self.gconf.set_string(self.prefs_key+"/device",self.dm_device)
    self.gconf.set_string(self.prefs_key+"/loop_file",self.loop_file)
    self.gconf.set_bool(self.prefs_key+"/auto_open",self.auto_open)
    self.fstab_entry=self.fstab_entry_for_dev('/dev/mapper/'+self.dm_name)
            
  def update_tip(self):
    if self.locked:
      state="locked"
    else:
      state="unlocked"
    try:
      self.tooltips.set_tip(self,"%s is %s"%(self.fstab_entry[1],state))
    except:
      pass
  def update_icon(self):
    if self.locked:
      self.image.set_from_file(INSTALL_PREFIX+"/lock.png")
    else:
      self.image.set_from_file(INSTALL_PREFIX+"/lock-open.png")

  def on_destroy(self,widget):
    print "destroying"
    self.unmount()
    
  def on_click(self,widget,event):
    if event.button!=1:
      return False
    if not self.dm_name:
      self.show_prefs()
      return True
    if self.locked:
      dialog=gtk.Dialog("Password",None,gtk.DIALOG_DESTROY_WITH_PARENT|gtk.DIALOG_MODAL,
        (gtk.STOCK_CANCEL,gtk.RESPONSE_REJECT,gtk.STOCK_OK,gtk.RESPONSE_ACCEPT))
      pwd=gtk.Entry()
      pwd.set_visibility(False)
      pwd.set_activates_default(True)
      dialog.set_default_response(gtk.RESPONSE_ACCEPT)
      dialog.vbox.add(pwd)
      dialog.show_all()
      if dialog.run()==gtk.RESPONSE_ACCEPT:
        if self.mount(pwd.get_text()):
          self.locked=False
          if self.auto_open and len(self.fstab_entry)>1:
            os.system("nautilus '%s'"%self.fstab_entry[1]);
      dialog.destroy()
    else:
      if self.unmount() or not self.is_mounted():
        self.locked=True
    self.update_icon()
    self.update_tip()
    return True

  def is_mounted(self):
    try:
      return os.system("mount|grep -q /dev/mapper/'%s'"%self.dm_name)==0
    except:
      return False
      
  def unmount(self):
    return os.system("umount '%s' && cryptsetup remove '%s'"%(self.fstab_entry[1],self.dm_name))==0

  def mount(self,pwd):
    opts=''
#    try:
#      if self.fstab_entry[3].split(',').index('ro')>0:
#        opts='--readonly'
#    except:
#      pass
    return os.system("cryptsetup remove '%s';echo '%s'|cryptsetup create '%s' '%s' %s && mount /dev/mapper/%s"%(self.dm_name,pwd,self.dm_name,self.dm_device,opts,self.dm_name))==0
          
  def on_about(self,a,b,applet):
    popup_menu = applet.get_popup_component()
#  print popup_menu.get_prop("/commands/About",'name')

#    print dir(popup_menu)
    aboutdialog=self.wTree.get_widget("aboutdialog")
    aboutdialog.set_version("0.0.1")
    aboutdialog.run()
    aboutdialog.hide()
    pass

  def show_prefs(self):
    prefs=self.wTree.get_widget("prefsdialog")
    dm_name=self.wTree.get_widget("name_entry")
    loop_file=self.wTree.get_widget("loopback_file_entry")
    dm_device=self.wTree.get_widget("device_entry")
    auto_open=self.wTree.get_widget("autoopen_checkbox")
    dm_name.set_text(self.dm_name)
    dm_device.set_text(self.dm_device)
    loop_file.set_text(self.loop_file)
    auto_open.set_active(self.auto_open)
    if prefs.run()==gtk.RESPONSE_OK:
      self.dm_name=dm_name.get_text()
      self.loop_file=loop_file.get_text()
      self.dm_device=dm_device.get_text()
      self.auto_open=auto_open.get_active()
      self.write_prefs()
    prefs.hide()

  def on_prefs(self,a,b,applet):
    self.show_prefs()
    pass

def applet_factory(applet, iid):
    applet.add(CryptSetupApplet(applet,iid))
    applet.show_all()
    return True

def activate_factory():
  gnomeapplet.bonobo_factory("OAFIID:GNOME_CryptSetupApplet_Factory", 
                              gnomeapplet.Applet.__gtype__, 
                              "hello", "0", applet_factory)

def main():
    if len(sys.argv) == 2 and sys.argv[1] == "-window":
        global INSTALL_PREFIX
        INSTALL_PREFIX='.'
        applet_window = gtk.Window(gtk.WINDOW_TOPLEVEL)
        applet_window.set_title("CryptoSetupApplet")
        applet_window.connect("destroy", gtk.main_quit)
        gnome.init("CryptoSetup Applet", "0.0.1")
        applet = gnomeapplet.Applet()
        applet_factory(applet, None)
        applet.reparent(applet_window)
        applet_window.show_all()
        gtk.main()
    else:
        activate_factory()

if __name__ == "__main__":
    main()
